home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Unsupported Libraries / PICTio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  18.8 KB  |  638 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2.  **                                                                             **
  3.  **     Module:        PICTio.c                                                 **
  4.  **                                                                          **
  5.  **                                                                          **
  6.  **                                                                          **
  7.  **     Purpose:     Read and write PICT files.                                 **
  8.  **                                                                          **
  9.  **                    There are two different "read" routines.                 **
  10.  **                    One uses QuickDraw, and so can draw any kind of PICT,     **
  11.  **                    but this only works on Macintoshes.                         **
  12.  **                                                                          **
  13.  **                    The other parses the PICT file directly, and only reads  **
  14.  **                    in a subset of the PICT opcodes, most particularly         **
  15.  **                    24-32 bit images (DirectBitsRect). This works cross          **
  16.  **                    platform, at least on big-endian machines (it works on     **
  17.  **                    the SGI).                                                 **
  18.  **                                                                          **
  19.  **                    The "write" routine comes in only one version.             **
  20.  **                    Both Macintoshes and non-Macintoshes write out PICT         **
  21.  **                    files directly. One advantage to the interface is that     **
  22.  **                    images may be written out in a piecewise fashion,         **
  23.  **                    one scaline at a time. This is difficult if not              **
  24.  **                    impossible to do using the Macintosh toolbox. The         **
  25.  **                    incremental writing of an image is handy in particular     **
  26.  **                    when band-rendering or otherwise rendering on a machine     **
  27.  **                    with a small amount of memory compared with the             **
  28.  **                    rendering task.                                             **
  29.  **                                                                          **
  30.  **                                                                          **
  31.  **                                                                          **
  32.  **     Copyright (C) 1992-1995 Apple Computer, Inc.  All rights reserved.     **
  33.  **                                                                          **
  34.  **                                                                          **
  35.  *****************************************************************************/
  36.  
  37. #if defined(applec) || defined(THINK_C) || defined(__MWERKS__)
  38. # include <Quickdraw.h>
  39. # include <Memory.h>
  40. #endif /* defined(applec) || defined(THINK_C) || defined(__MWERKS__) */
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include "QD3D.h"
  45. #include "PackBytes.h"
  46. #include "PICTio.h"
  47.  
  48.  
  49.  
  50. #if defined(applec) || defined(THINK_C) || defined(__MWERKS__)
  51.  
  52. /****************************************************************
  53.  * Read PICT - Macintosh version.
  54.  ****************************************************************/
  55.  
  56. static FILE *PICTfd;
  57.  
  58.  
  59. /*===========================================================================*\
  60.  *
  61.  *    Routine:    GetPICTData()
  62.  *
  63.  *    Comments:    Bottleneck proc.
  64.  *
  65. \*===========================================================================*/
  66.  
  67. /* This is the replacement for the StdGetPic routine */
  68. static pascal void GetPICTData(
  69.     Ptr     dataPtr, 
  70.     short     byteCount)
  71. {
  72.     fread(dataPtr, 1, byteCount, PICTfd);
  73. }
  74.  
  75. /*===========================================================================*\
  76.  *
  77.  *    Routine:    ErReadPICT()
  78.  *
  79.  *    Comments:    PICT reading
  80.  *
  81. \*===========================================================================*/
  82.  
  83. unsigned char *ErReadPICT(        /* Returns a pointer to the baseAddr */
  84.     long             *width,     /* Returns the width of the image */
  85.     long             *height,     /* Returns the height of the image */
  86.     long             *rowBytes,     /* Returns the rowBytes of the image */
  87.     FILE             *fd)        /* The I/O descriptor */
  88. {
  89.     unsigned char *image;
  90.  
  91.     CQDProcs     cqdProcs;
  92.     PicHandle     picHandle;
  93.     Rect         pictR;
  94.     CGrafPort     port;
  95.     GrafPtr     savePort;
  96.     PixMap         *pm;
  97.     GDHandle     gd, saveGD;
  98.     
  99.     PICTfd = fd;
  100.  
  101.  
  102.     /* Read the picture frame size */
  103.     fseek(fd, 512L, 0);
  104.     picHandle = (PicHandle)NewHandle(sizeof (Picture));
  105.     HLock((Handle)picHandle);
  106.     fread(*picHandle, sizeof(Picture), 1, fd);
  107.     pictR = (*picHandle)->picFrame;
  108.     HUnlock((Handle)picHandle);
  109.  
  110.     /* Allocate a bitmap */
  111.     *width = pictR.right - pictR.left;
  112.     *height = pictR.bottom - pictR.top;
  113.     *rowBytes = (*width) * 4;
  114.     if ((image = malloc((*rowBytes) * (*height))) == NULL) {
  115.         fprintf(stderr, "Can't alloc image\n");
  116.         return (NULL);
  117.     }
  118.  
  119.     GetPort(&savePort);
  120.     
  121.     /* Allocate a GDevice */
  122.     gd = NewGDevice(3, -1);
  123.     (*gd)->gdType = 2;
  124.     pm = *((*gd)->gdPMap);
  125.     pm->rowBytes = 0x8000 | *rowBytes;
  126.     pm->baseAddr = (Ptr)image;
  127.     pm->bounds = pictR;
  128.     pm->pixelType = 16;
  129.     pm->pixelSize = 32;
  130.     pm->cmpCount = 3;
  131.     pm->cmpSize = 8;
  132.     pm->pmTable = 0;
  133.     (*gd)->gdRect = pictR;
  134.     SetDeviceAttribute(gd, 0, 1);
  135.     SetDeviceAttribute(gd, 11, 0);
  136.     SetDeviceAttribute(gd, 13, 0);
  137.     SetDeviceAttribute(gd, 14, 0);
  138.     SetDeviceAttribute(gd, 15, 1);
  139.     
  140.     saveGD = GetGDevice();
  141.     SetGDevice(gd);
  142.  
  143.     /* Allocate and initialize a CGrafPort */
  144.     OpenCPort(&port);
  145.     CopyPixMap((*gd)->gdPMap, port.portPixMap);
  146.     
  147.     /* Hack the visRgn */
  148.     RectRgn(port.visRgn, &pictR);
  149.  
  150.     /* change the procs in the port */
  151.     SetStdCProcs(&cqdProcs);
  152. #if defined(__MWERKS__) || defined(ppcinterfaces) || (THINK_C > 6)
  153.     cqdProcs.getPicProc = NewQDGetPicProc(GetPICTData);
  154. #elif defined(THINK_C) && (THINK_C <= 6)
  155.     cqdProcs.getPicProc = (Ptr)GetPICTData;
  156. #else
  157.     cqdProcs.getPicProc = GetPICTData;
  158. #endif
  159.     port.grafProcs = &cqdProcs;
  160.     
  161.     SetPort((GrafPtr)&port);
  162.  
  163.     DrawPicture(picHandle, &pictR);
  164.  
  165.     SetPort(savePort);
  166.     SetGDevice(saveGD);
  167.     CloseCPort(&port);
  168.     DisposGDevice(gd);
  169.  
  170.     KillPicture(picHandle);
  171.     
  172.     return (image);
  173. }
  174.  
  175. #else /* !macintosh */
  176.  
  177.  
  178. /****************************************************************
  179.  * Read PICT - Non-Macintosh method: reading only 24-bit images.
  180.  ****************************************************************/
  181.  
  182. typedef char     *Ptr;
  183. typedef long     Fixed;
  184. typedef void    **CTabHandle;
  185.  
  186. typedef struct Rect {
  187.     short     top;
  188.     short     left;
  189.     short     bottom;
  190.     short     right;
  191. } Rect;
  192.  
  193. typedef struct Picture {
  194.     short     picSize;
  195.     Rect     picFrame;
  196. } Picture;
  197.  
  198. typedef struct PixMap {
  199.     Ptr         baseAddr;         /*  pointer to image            */
  200.     short         rowBytes;         /*  offset to next line            */
  201.     Rect         bounds;         /*  encloses bitmap                */
  202.     short         pmVersion;         /*  pixMap version number        */
  203.     short         packType;         /*  defines packing format        */
  204.     long         packSize;       /*  length of pixel data        */
  205.     Fixed         hRes;           /*  horiz. resolution (ppi)        */
  206.     Fixed         vRes;            /*  vert. resolution (ppi)        */
  207.     short         pixelType;        /*  defines pixel type            */
  208.     short         pixelSize;        /*  # bits in pixel                */
  209.     short         cmpCount;        /*  # components in pixel        */
  210.     short         cmpSize;        /*  # bits per component        */
  211.     long         planeBytes;       /*  offset to next plane        */
  212.     CTabHandle pmTable;         /*  color map for this pixMap    */
  213.     long         pmReserved;        /*  for future use. MUST BE 0    */
  214. } PixMap;
  215.  
  216.  
  217. /*===========================================================================*\
  218.  *
  219.  *    Routine:    ErReadPICT()
  220.  *
  221.  *    Comments:    This reads only 24-bit images, but works on any machine.
  222.  *
  223. \*===========================================================================*/
  224.  
  225. unsigned char *ErReadPICT(        /* Returns a pointer to the baseAddr */
  226.     long             *width,     /* Returns the width of the image */
  227.     long             *height,     /* Returns the height of the image */
  228.     long             *rowBytes,     /* Returns the rowBytes of the image */
  229.     FILE             *f            /* The I/O descriptor */
  230. )
  231. {
  232.     unsigned char *image = NULL;
  233.     Picture         pictHeader;    /* Assume that we like what it says */
  234.     struct             VersionBundle { short versionOpcode, version; } versionBundle;
  235.     typedef struct { unsigned char a, r, g, b; } TColorI;
  236.  
  237.     fseek(f, 512L, 0);    /* Skip 512 byte header */
  238.  
  239.     fread(&pictHeader, sizeof(pictHeader), 1, f);
  240.     
  241.     fread(&versionBundle, sizeof(versionBundle), 1, f);
  242.     if (versionBundle.versionOpcode != 0x0011 || versionBundle.version != 0x02FF) {
  243.         fprintf(stderr, 
  244.                 "Bad version bundle: %04X %04X", 
  245.                 versionBundle.versionOpcode, 
  246.                 versionBundle.version);
  247.         return (0);
  248.     }
  249.     
  250.     for (;;) {
  251.         short opCode;
  252.         if (fread(&opCode, sizeof(opCode), 1, f) == 0)
  253.             break;
  254.         switch (opCode) {
  255.             case 0x0000:    /* NOP */
  256.                 break;
  257.             
  258.             case 0x0011:    /* Version */
  259.             {
  260.                 short version;
  261.                 fread(&version, sizeof(version), 1, f);
  262.                 if (version != 0x02FF) {
  263.                     fprintf(stderr, "Version %04X != 0x02FF", version);
  264.                     return (0);
  265.                 }
  266.             } break;
  267.             
  268.             case 0x0C00:    /* Header */
  269.             {
  270.                 struct HeaderBundle {
  271.                     long    sizeField;        /* -1 */
  272.                     Fixed    left;
  273.                     Fixed    top;
  274.                     Fixed    right;
  275.                     Fixed    bottom;
  276.                     long    appleReserved;    /* 0 */
  277.                 } headerBundle;
  278.                 fread(&headerBundle, sizeof(headerBundle), 1, f);
  279.             } break;
  280.  
  281.             case 0x001E:    /* defHilite */
  282.                 break;
  283.             
  284.             case 0x0001:    /* ClipRegion */
  285.             {
  286.                 unsigned short clipRgnSize;
  287.                 fread(&clipRgnSize, sizeof(clipRgnSize), 1, f);
  288.                 fseek(f, (long)(clipRgnSize-2), 1);        /* Skip clip region */
  289.             } break;
  290.             
  291.             case 0x009A:    /* directBitsRect */
  292.             {    
  293.                 struct ImageStuff {
  294.                     PixMap    pixmap;
  295.                     Rect    srcRect;
  296.                     Rect    dstRect;
  297.                     short    mode;
  298.                 } imageStuff;
  299.                 
  300.                 /* Get a buffer to hold the image */
  301. #if defined(applec) || defined(THINK_C)
  302.                 fread(&imageStuff, sizeof(imageStuff), 1, f);
  303. #else /* !macintosh */
  304.                 /* get around non-longword alignment */
  305.                 fread(&imageStuff.pixmap.baseAddr,        sizeof(long),    1,    f);
  306.                 fread(&imageStuff.pixmap.rowBytes,        sizeof(short),    1,    f);
  307.                 fread(&imageStuff.pixmap.bounds,        sizeof(short),    4,    f);    /* left, top, right, bottom */
  308.                 fread(&imageStuff.pixmap.pmVersion,        sizeof(short),    2,    f);    /* pmVersion, packType */
  309.                 fread(&imageStuff.pixmap.packSize,        sizeof(long),    1,    f);
  310.                 fread(&imageStuff.pixmap.hRes,            sizeof(Fixed),    2,    f);    /* hRes, vRes */
  311.                 fread(&imageStuff.pixmap.pixelType,        sizeof(short),    4,    f);    /* pixelType, pixelSize, cmpCount, cmpSize */
  312.                 fread(&imageStuff.pixmap.planeBytes,    sizeof(long),    3,    f);    /* planeBytes, pmTable, pmReserved */
  313.                 fread(&imageStuff.srcRect,                sizeof(short),    4,    f);    /* left, top, right, bottom */
  314.                 fread(&imageStuff.dstRect,                sizeof(short),    4,    f);    /* left, top, right, bottom */
  315.                 fread(&imageStuff.mode,                    sizeof(short),    1,    f);
  316. #endif /* macintosh */
  317.  
  318.                 *width = imageStuff.srcRect.right - imageStuff.srcRect.left;
  319.                 *height = imageStuff.srcRect.bottom - imageStuff.srcRect.top;
  320.                 *rowBytes = 4 * (*width);
  321.                 image = malloc(*rowBytes * (*height));
  322.                     
  323.                 if (image != NULL) {
  324.                     char lineBuffer[5000];    /* scanline of components */
  325.                     char compLine[5000];    /* compressed scanline of components */
  326.                     register long i;
  327.                     int j;
  328.                     register char *p, *q;
  329.                     char *q0;
  330.                     int wordByteCount = (int)((imageStuff.pixmap.rowBytes & 0x3FFF) > 250);    /* If byteCount is a word */
  331.  
  332.                     for (q0 = (char *)image, j = *height; j--; q0 += *rowBytes) {
  333.                     
  334.                         /* Read a compressed scanline */
  335.                         if (wordByteCount) {
  336.                             unsigned short size;
  337.                             fread(&size, sizeof(size), 1, f);
  338.                             fread(compLine, size, 1, f);
  339.                         }
  340.                         else {
  341.                             unsigned char size;
  342.                             fread(&size, sizeof(size), 1, f);
  343.                             fread(compLine, size, 1, f);
  344.                         }
  345.                         
  346.                         /* Decompress the scanline */
  347.                         UnpackBytes(compLine, lineBuffer, 3*(*width));
  348.                     
  349.                         /* Interlace components into image */
  350.                         p = lineBuffer;
  351.                         for (i = *width, q = (char *)(&((TColorI*)q0)->r); i--; p++, q += sizeof(TColorI))
  352.                             *q = *p;    /* Comb out red */
  353.                         for (i = *width, q = (char *)(&((TColorI*)q0)->g); i--; p++, q += sizeof(TColorI))
  354.                             *q = *p;    /* Comb out green */
  355.                         for (i = *width, q = (char *)(&((TColorI*)q0)->b); i--; p++, q += sizeof(TColorI))
  356.                             *q = *p;    /* Comb out blue */
  357.                     }
  358.                     if (ftell(f) & 1)
  359.                         getc(f);
  360.                 }
  361.                 else {
  362.                     fprintf(stderr, "Unable to allocate buffer(%d, %d) for ReadPICT", *width, *height);
  363.                 }
  364.             } break;
  365.             
  366.             case 0x00FF:    /* End opcode */
  367.                 return (image);
  368.                 
  369.             default:
  370.                 fprintf(stderr, "Unknown opcode: %04X", opCode);
  371.                 return (image);
  372.         }
  373.     }
  374.     
  375.     return (NULL);
  376. }
  377.  
  378. #endif /* !macintosh */
  379.  
  380.  
  381.  
  382. typedef struct PICTheader {
  383.     /* 512 bytes of 0's */
  384.     Picture    picture;
  385.  
  386.     short    versionOpcode;    /* 0x0011 */
  387.     short    version;        /* 0x02FF */
  388.     
  389.     short    headerOpcode;    /* 0x0C00 */
  390.     long    sizeField;        /* -1 */
  391.     Fixed    left;
  392.     Fixed    top;
  393.     Fixed    right;
  394.     Fixed    bottom;
  395.     long    appleReserved;    /* 0 */
  396.     
  397.     short    maxClipRegion[6];    /* 0001 000A 8001 8001 7FFF 7FFF */
  398.     
  399.     short    directBitsRect;    /* 009A */
  400.     PixMap    pixmap;
  401.     Rect    srcRect;
  402.     Rect    dstRect;
  403.     short    mode;
  404.     /* PixelData */
  405. } PICTHeader;
  406.  
  407.  
  408. /*===========================================================================*\
  409.  *
  410.  *    Routine:    StartWritePICT()
  411.  *
  412.  *    Comments:    Write header for a 24-bit PICT file without using QuickDraw.
  413.  *
  414. \*===========================================================================*/
  415.  
  416. long StartWritePICT(
  417.     long     width, 
  418.     long     height, 
  419.     FILE     *f)
  420. {
  421.     struct PICTheader pictHeader;
  422.  
  423.     {    /* Write out the 512 byte header pad */
  424.         long headPad[512/sizeof(long)];
  425.         register long *lp = headPad;
  426.         register int i;
  427.         char *cHeadPad = (char *)headPad;
  428.         
  429.         for (i = 512/sizeof(long); i--; *lp++ = 0) {
  430.             /* do nothing */ ;    /* Clear header pad */
  431.         }
  432.         
  433.         cHeadPad[0] = 'P';    /* Record the type of the file */
  434.         cHeadPad[1] = 'I';
  435.         cHeadPad[2] = 'C';
  436.         cHeadPad[3] = 'T';
  437.         
  438.         fwrite(cHeadPad, 1, 512, f);    /* Write out the header pad */
  439.     }
  440.     
  441.     /* Make SURE the size of the image is adequately recorded */
  442.     pictHeader.picture.picSize =            0;
  443.     pictHeader.picture.picFrame.top =        0;
  444.     pictHeader.picture.picFrame.left =    0;
  445.     pictHeader.picture.picFrame.bottom =    height;
  446.     pictHeader.picture.picFrame.right =    width;
  447.     pictHeader.versionOpcode =            0x0011;
  448.     pictHeader.version =                    0x02FF;    /* Version 2 */
  449.     pictHeader.headerOpcode =                0x0C00;
  450.     pictHeader.sizeField =                -1;
  451.     pictHeader.left =                        0;
  452.     pictHeader.top =                        0;
  453.     pictHeader.right =                    width << 16;
  454.     pictHeader.bottom =                    height << 16;
  455.     pictHeader.appleReserved =            0;
  456.     pictHeader.maxClipRegion[0] =            0x0001;    /* Clip region opcode */
  457.     pictHeader.maxClipRegion[1] =            0x000A;    /* sizeof (Rect) + 2 */
  458.     pictHeader.maxClipRegion[2] =            0x8001;    /* top */
  459.     pictHeader.maxClipRegion[3] =            0x8001;    /* left */
  460.     pictHeader.maxClipRegion[4] =            0x7FFF;    /* bottom */
  461.     pictHeader.maxClipRegion[5] =            0x7FFF;    /* right */
  462.     pictHeader.directBitsRect =            0x009A;
  463.     pictHeader.pixmap.baseAddr =            (Ptr)0x000000FF;
  464.     pictHeader.pixmap.rowBytes =            (4 * width) | 0x8000;
  465.     pictHeader.pixmap.bounds.top =        0;
  466.     pictHeader.pixmap.bounds.left =        0;
  467.     pictHeader.pixmap.bounds.bottom =        height;
  468.     pictHeader.pixmap.bounds.right =        width;
  469.     pictHeader.pixmap.pmVersion =            0;
  470.     pictHeader.pixmap.packType =            4;
  471.     pictHeader.pixmap.packSize =            0;
  472.     pictHeader.pixmap.hRes =                72 << 16;
  473.     pictHeader.pixmap.vRes =                72 << 16;
  474.     pictHeader.pixmap.pixelType =            16;
  475.     pictHeader.pixmap.pixelSize =            32;
  476.     pictHeader.pixmap.cmpCount =            3;
  477.     pictHeader.pixmap.cmpSize =            8;
  478.     pictHeader.pixmap.planeBytes =        0;
  479.     pictHeader.pixmap.pmTable =            0;
  480.     pictHeader.pixmap.pmReserved =        0;
  481.     pictHeader.srcRect.top =                0;
  482.     pictHeader.srcRect.left =                0;
  483.     pictHeader.srcRect.bottom =            height;
  484.     pictHeader.srcRect.right =            width;
  485.     pictHeader.dstRect.top =                0;
  486.     pictHeader.dstRect.left =                0;
  487.     pictHeader.dstRect.bottom =            height;
  488.     pictHeader.dstRect.right =            width;
  489.     pictHeader.mode =                        0x0040;    /* Dither */
  490.     
  491. #if defined(applec) || defined(THINK_C)
  492.     fwrite(&pictHeader, sizeof(pictHeader), 1, f);
  493. #else /* !macintosh, but not for the Cray */
  494.     fwrite(&pictHeader.picture.picSize,    sizeof(short),    1,    f);
  495.     fwrite(&pictHeader.picture.picFrame,    sizeof(short),    4,    f);    /* left, top, right, bottom */
  496.  
  497.     fwrite(&pictHeader.versionOpcode,        sizeof(short),    2,    f);    /* versionOpCode, version */
  498.  
  499.     fwrite(&pictHeader.headerOpcode,        sizeof(short),    1,    f);
  500.     fwrite(&pictHeader.sizeField,            sizeof(long),    1,    f);
  501.     fwrite(&pictHeader.left,                sizeof(Fixed),    4,    f);    /* left, top, right, bottom */
  502.     fwrite(&pictHeader.appleReserved,        sizeof(long),    1,    f);
  503.  
  504.     fwrite(pictHeader.maxClipRegion,        sizeof(short),    6,    f);
  505.  
  506.     fwrite(&pictHeader.directBitsRect,    sizeof(short),    1,    f);
  507.     fwrite(&pictHeader.pixmap.baseAddr,    sizeof(long),    1,    f);
  508.     fwrite(&pictHeader.pixmap.rowBytes,    sizeof(short),    1,    f);
  509.     fwrite(&pictHeader.pixmap.bounds,        sizeof(short),    4,    f);    /* left, top, right, bottom */
  510.     fwrite(&pictHeader.pixmap.pmVersion,    sizeof(short),    2,    f);    /* pmVersion, packType */
  511.     fwrite(&pictHeader.pixmap.packSize,    sizeof(long),    1,    f);
  512.     fwrite(&pictHeader.pixmap.hRes,        sizeof(Fixed),    2,    f);    /* hRes, vRes */
  513.     fwrite(&pictHeader.pixmap.pixelType,    sizeof(short),    4,    f);    /* pixelType, pixelSize, cmpCount, cmpSize */
  514.     fwrite(&pictHeader.pixmap.planeBytes,    sizeof(long),    3,    f);    /* planeBytes, pmTable, pmReserved */
  515.     fwrite(&pictHeader.srcRect,            sizeof(short),    4,    f);    /* left, top, right, bottom */
  516.     fwrite(&pictHeader.dstRect,            sizeof(short),    4,    f);    /* left, top, right, bottom */
  517.     fwrite(&pictHeader.mode,                sizeof(short),    1,    f);
  518. #endif /* macintosh */
  519.  
  520.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  521. }
  522.  
  523.  
  524.  
  525. /*===========================================================================*\
  526.  *
  527.  *    Routine:    WritePICTLines()
  528.  *
  529.  *    Comments:    Write the specified number of lines.
  530.  *
  531. \*===========================================================================*/
  532.  
  533. long WritePICTLines(
  534.     unsigned char     *buf, 
  535.     long             width, 
  536.     long             height, 
  537.     long             rowBytes, 
  538.     FILE             *f
  539. )
  540. {
  541.     unsigned char             lineBuffer[5200];        /* scanline of components */
  542.     unsigned char             compLine[5200];    /* compressed scanline of components */
  543.     register int             i;
  544.     int                     wordByteCount;
  545.     register unsigned char     *p, *q;
  546.     unsigned char             *q0;
  547.  
  548.     wordByteCount = (int)(width > 250/4);    /* If byteCount is a word */
  549.     
  550.     for (q0 = buf; height--; q0 += rowBytes) {
  551.     
  552.         /* Comb components out of image */
  553.         p = lineBuffer;
  554.         for (i = width, q = q0 + 1; i--; p++, q += 4)
  555.             *p = *q;    /* Comb out red */
  556.         for (i = width, q = q0 + 2; i--; p++, q += 4)
  557.             *p = *q;    /* Comb out green */
  558.         for (i = width, q = q0 + 3; i--; p++, q += 4)
  559.             *p = *q;    /* Comb out blue */
  560.     
  561.         /* Write out the size of this compressed scanline */
  562.         i = (int)PackBytes((char *)lineBuffer, (char *)compLine, 3*width);
  563.         if (wordByteCount) {
  564.             unsigned char size[2];
  565.             size[0] = (unsigned char)(i >> 8);
  566.             size[1] = (unsigned char)i;
  567.             fwrite(size, 2, 1, f);
  568.         }
  569.         else {
  570.             unsigned char size = i;
  571.             fwrite(&size, 1, 1, f);
  572.         }
  573.         
  574.         /* Write out the compressed scanline */
  575.         fwrite(compLine, 1, i, f);
  576.     }
  577.     
  578.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  579. }
  580.  
  581.  
  582. /*===========================================================================*\
  583.  *
  584.  *    Routine:    EndWritePICT()
  585.  *
  586.  *    Comments:    Close up PICT file.
  587.  *
  588. \*===========================================================================*/
  589.  
  590. long EndWritePICT(
  591.     FILE     *f
  592. )
  593. {
  594.     short code;
  595.     
  596.     /* Write end opcode */
  597.     if (ftell(f) & 1) putc(0, f);    /* Make sure we are word aligned */
  598.     code = 0x00FF;
  599.     fwrite(&code, sizeof(short), 1, f);
  600.     
  601.     /* Backfit picSize */
  602.     code = (short)(ftell(f) - 512L);
  603.     fseek(f, 512L, 0);
  604.     fwrite(&code, 2, 1, f);
  605.     
  606.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  607. }
  608.  
  609.  
  610. /*===========================================================================*\
  611.  *
  612.  *    Routine:    ErWritePICT()
  613.  *
  614.  *    Comments:    Write a PICT file.
  615.  *
  616. \*===========================================================================*/
  617.  
  618. long ErWritePICT(
  619.     unsigned char     *baseAddr, 
  620.     long             width, 
  621.     long             height, 
  622.     long             rowBytes, 
  623.     FILE             *f
  624. )
  625. {    
  626.     if (height < 0) {
  627.         height = -height;    
  628.         /* This takes care of the case when Y goes up; rowBytes should be < 0 */
  629.     }
  630.     
  631.     StartWritePICT(width, height, f);
  632.     WritePICTLines(baseAddr, width, height, rowBytes, f);
  633.     EndWritePICT(f);
  634.     
  635.     return (!ferror(f));    /* 1 if no error, 0 otherwise */
  636. }
  637.  
  638.